﻿#region references
using System;
using System.Collections.Generic;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
using System.Web.Security;

/* Project dependencies */
using IcaGames.Objects;
using IcaGames.Database;
using IcaGames.Database.ObjectManagement;
using IcaGames.Logging;
using IcaGames.Security;
#endregion

public partial class usercontrols_GameDetails : System.Web.UI.UserControl
{

    #region public attributes
    public List<Game> _favoriteGames
    {
        set { ViewState["favorites"] = value; }
        get
        {
            List<Game> ret = null;
            if ((List<Game>)ViewState["favorites"] != null)
                ret = (List<Game>)ViewState["favorites"];
            return ret;
        }
    }

    public List<Review> _reviews
    {
        set { ViewState["reviews"] = value; }
        get 
        {
            List<Review> ret = null;
            if ((List<Review>)ViewState["reviews"] != null)
                ret = (List<Review>)ViewState["reviews"];
            return ret;
        }
    }

    public int _viewIndex
    {
        set { Session["viewIndex"] = value; }
        get
        {
            int ret = 0;
            if (Session["viewIndex"] != null)
                ret = (int)Session["viewIndex"];
            return ret;
        }
    }
    #endregion

    protected void Page_Init(object sender, EventArgs e)
    {
        /* Check if the user is is authenticated and restore the MultiView ViewIndex */
        if (Page.User.Identity.IsAuthenticated)
        {
            MultiView1.ActiveViewIndex = _viewIndex;
            if (_viewIndex == 0) { lbViewGameDetails.Enabled = false; lbViewReviews.Enabled = true; lbViewFavorites.Enabled = true; }
            else if (_viewIndex == 1) { lbViewGameDetails.Enabled = true; lbViewReviews.Enabled = true; lbViewFavorites.Enabled = false; }
            else if (_viewIndex == 2)
            {
                lbViewGameDetails.Enabled = true;
                lbViewReviews.Enabled = false;
                lbViewFavorites.Enabled = true;

                CheckUserReview();
            }
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            try
            {
                SetTextBoxValidator();

                /* Get gameNr so that the specified information can be loaded from the database */
                string[] queryString = Request.QueryString["g"].Split('_');
                string searchText = Request.QueryString["s"];
                Game game = new Game();

                lbBackToSearchResults.CommandArgument = searchText;

                if (!GameManagement.GetGame(int.Parse(queryString[0]), game, queryString[1]))
                {
                    /* Set the error message using the ErrorTable UserControl */
                    ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de Game details. Probeer het nogmaals.";
                    ucErrors._pnlVisibility = true;
                    pnlContents.Visible = false;
                }
                else
                { SetGameDetails(game); GetFavoriteGames(); GetGameReviews(); }
            }
            catch (Exception ex)
            {
                Log.CreateLog("Exception while getting QueryString for GameDetails", "GAMEDETAILS");
                Log.CreateLog(ex.Message, "GAMEDETAILS");

                /* Set the error message using the ErrorTable UserControl */
                ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de Game details. Probeer het nogmaals.";
                ucErrors._pnlVisibility = true;
                pnlContents.Visible = false;
            }
        }
        else
        {
            SetFavoriteDetails();
        }
    }

    /*
     * Function that sets the validator for the TextBox txtWriteReview.
     * The user can't insert a review  that is longer than 1024 characters.
     */ 
    private void SetTextBoxValidator()
    {
        TextBox txtWriteReview = MultiView1.Views[2].FindControl("txtWriteReview") as TextBox;
        TextBox txtReviewCount = MultiView1.Views[2].FindControl("txtReviewCount") as TextBox;

        txtWriteReview.Attributes["onkeyup"] = "textCounter(this," + txtReviewCount.ClientID + ", 1024)";
        txtWriteReview.Attributes["onkeydown"] = "textCounter(this," + txtReviewCount.ClientID + ", 1024)";
    }

    /*
     * Function that is executed when the ImageButton to refresh the Game stock is clicked.
     * 
     * Get's an updated stock for the selected Game.
     */
    protected void RefreshGameStock(object sender, ImageClickEventArgs e)
    {
        try
        {
            int gameStock = 0;
            string[] param = Request.QueryString["g"].Split('_');
            int platformId = PlatformValue.GetPlatformValue(param[1]);
            if ((gameStock = GameManagement.GetGameStock(int.Parse(param[0]), platformId)) == -1)
            {
                /* Set the error message using the ErrorTable UserControl */
                ucErrors._labelText = "Er is een fout opgetreden bij het verversen van de voorraad. Probeer het nogmaals.";
                ucErrors._pnlVisibility = true;
            }
            else { lblGameStock.Text = gameStock.ToString(); }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception while refreshing the Game stock", "GAMEDETAILS");
            Log.CreateLog(ex.Message, "GAMEDETAILS");

            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij het verversen van de voorraad. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
        }
    }

    /*
     * Function to set the Favorites table with a few other Games.
     */
    private void GetFavoriteGames()
    {
        string[] queryString = Request.QueryString["g"].Split('_');

        if (_favoriteGames == null) { _favoriteGames = new List<Game>(); }
        if (!GameManagement.GetFavoriteGames(_favoriteGames, int.Parse(queryString[0])))
        {
            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van favorieten. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
            pnlContents.Visible = false;
        }
        else { SetFavoriteDetails(); }
    }

    /*
     * Function to set the Favorite Games details when the list is loaded.
     */
    private void SetFavoriteDetails()
    {
        try
        {
            foreach (Game g in _favoriteGames)
            {
                /* Add four ImageButtons to the Panel pnlFavorites with Game information */
                pnlFavorites.Controls.Add(new LiteralControl("<td>"));
                ImageButton ibtn = new ImageButton();

                /* Set ImageButton ImageUrl */
                string description = PlatformDescription.GetDescription(g.Platform);
                string platform = Thumb.GetImagePlatform(description);

                string path = Server.MapPath("~/upload/") + g.GameNr + "/" + platform + "_thumb.jpg";
                if (!File.Exists(path)) { ibtn.ImageUrl = "../../img/no-image.png"; }
                else { ibtn.ImageUrl = "../../upload/" + g.GameNr + "/" + platform + "_thumb.jpg"; }

                /* Set ImageButton ToolTip */
                ibtn.ToolTip = String.Format("Titel: " + g.Title + "\r\n" + "Uitgever: " + g.Publisher.Name +
                    "\r\n" + "Prijs: €" + g.Price.ToString().Replace('.', ','));

                /* Set ImageButton OnClick and CommandArgument event */
                ibtn.CommandArgument = g.GameNr.ToString() + "_" + g.Platform.ToString();
                ibtn.Click += GetGameDetails;

                pnlFavorites.Controls.Add(ibtn);
                pnlFavorites.Controls.Add(new LiteralControl("</td>"));
            }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception while setting Favorite Game details", "GAMEDETAILS");
            Log.CreateLog(ex.Message, "GAMEDETAILS");

            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de favoriete Games lijst. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
            pnlContents.Visible = false;
        }
    }

    /*
     * Function that is executed when the LinkButton to get back to the search results is clicked.
     * 
     * Redirects the user back to the previous page with search results.
     */
    protected void GetGameDetails(object sender, ImageClickEventArgs e)
    {
        string game = ((ImageButton)sender).CommandArgument;
        Response.Redirect("~/GameDetails.aspx?g=" + game);
    }

    /*
     * Function to set the game details for the specified game.
     * 
     * @param
     * game: The specified game which details have to be set.
     */
    private void SetGameDetails(Game game)
    {
        lblGameTitle.Text = game.Title;
        lblGameStock.Text = game.Stock.ToString();
        lblGamePrice.Text = "€ " + String.Format("{0:0,##}", game.Price.ToString().Replace('.', ','));
        lbGamePublisher.Text = game.Publisher.Name;
        lbGamePublisher.CommandArgument = game.Publisher.PublisherId.ToString();
        btnAddToCart.CommandArgument = game.GameNr + "_" + game.Platform;
        if (game.DescriptionLong.Length != 0) { lblGameDescriptionLong.Text = game.DescriptionLong; }
        else { lblGameDescriptionLong.Text = "Geen uitgebreide beschrijving beschikbaar."; }

        /* Set the Platform Label correctly */
        Platform pf = PlatformValue.GetPlatform(game.Platform.ToString());
        lblGamePlatform.Text = PlatformDescription.GetDescription(pf);

        /* Get the thumb image that belongs with the selected game */
        string platform = Thumb.GetImagePlatform(lblGamePlatform.Text);
        string path = Server.MapPath("~/upload/") + game.GameNr + "/" + platform + "_thumb.jpg";

        if (!File.Exists(path)) { iGamePicture.ImageUrl = "../../img/no-image.png"; }
        else { iGamePicture.ImageUrl = "../../upload/" + game.GameNr + "/" + platform + "_thumb.jpg"; }

        /* Fill Publisher popup information */
        lblPublisherName.Text = game.Publisher.Name;

        string imgPath = Server.MapPath("~/upload/publishers/") + game.Publisher.PublisherId + "/" +
                game.Publisher.PublisherId + ".jpg";

        if (File.Exists(imgPath))
        {
            ibtnPublisher.ImageUrl = "../../upload/publishers/" + game.Publisher.PublisherId + "/" +
                game.Publisher.PublisherId + ".jpg";
        }
        else
        {
            ibtnPublisher.ImageUrl = "../../img/no-logo.png";
        }

        GetPublisherGames(game.Publisher.PublisherId);
    }

    /*
     * Function that is executed when the LinkButton lbGameTitle is clicked.
     * 
     * Redirects the user to the Game details page of the selected Game.
     */ 
    protected void GetGameDetails(object sender, EventArgs e)
    {
        string queryString = ((LinkButton)sender).CommandArgument;
        string searchText = lbBackToSearchResults.CommandArgument;
        Response.Redirect("~/GameDetails.aspx?g=" + queryString +
            "&s=" + searchText);
    }

    /*
     * Function to get a list with Games from a specified Publisher.
     * 
     * @param
     * publisherId: The id of the specified Publisher.
     */ 
    private void GetPublisherGames(int publisherId)
    {
        List<Game> games = new List<Game>();
        if (GameManagement.GetPublisherGames(publisherId, games))
        {
            gvPublisherGames.DataSource = games;
            gvPublisherGames.DataBind();
        }
    }

    /*
     * Function that is executed when the event RowDataBound is fired.
     * 
     */
    protected void gvPublisherGames_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        try
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                Label lblGamePrice = e.Row.FindControl("lblGamePrice") as Label;
                LinkButton lbGameTitle = e.Row.FindControl("lbGameTitle") as LinkButton;
                Label lblGameStock = e.Row.FindControl("lblGameStock") as Label;
                Label lblGamePlatform = e.Row.FindControl("lblGamePlatform") as Label;
                Button btnOrderGame = e.Row.FindControl("btnOrderGame") as Button;

                if (btnOrderGame != null) { btnOrderGame.Click += AddToCart; }

                /* Set the description for the Game Platform */
                if (lblGamePlatform != null)
                {
                    Platform pf = PlatformValue.GetPlatform(lblGamePlatform.Text);
                    lblGamePlatform.Text = PlatformDescription.GetDescription(pf);
                }

                /* Set Click event for lbGameTitle */
                if (lbGameTitle != null) { lbGameTitle.Click += GetGameDetails; }

                /* Set ToolTip for lblGameStock */
                if (lblGameStock != null)
                {
                    if (lblGameStock.Text.Equals("0")) { lblGameStock.ToolTip = "Dit artikel is helaas niet op voorraad"; }
                    else { lblGameStock.ToolTip = "Dit artikel is op voorraad"; }
                }

                /* Set the correct format for the Game price */
                if (lblGamePrice != null) { lblGamePrice.Text = "€ " + String.Format("{0:0,##}", lblGamePrice.Text.Replace('.', ',')); }
            }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception in gvSearchResults RowDataBound", "SEARCHGAME");
            Log.CreateLog(ex.Message, "SEARCHGAME");
        }
    }

    /*
     * Function that is executed when the Button btnAddToCart is clicked.
     * 
     * Add's the specified game to the shopping cart of the user.
     */
    protected void AddToCart(object sender, EventArgs e)
    {
        string[] param = ((Button)sender).CommandArgument.Split('_');
        Game g = new Game();
        ShoppingCart c = new ShoppingCart();

        if (GameManagement.GetGame(int.Parse(param[0]), g, param[1]))
        {
            if (Session["cart"] == null) { c.Games = new List<Game>(); }
            else { c = (ShoppingCart)Session["cart"]; }
            c.Games = CartManagement.AddGameToCart(c.CartId, c.Games, g);
            Session["cart"] = c;

            if (Session["cartPrice"] != null)
            {
                if (Page.User.Identity.IsAuthenticated)
                {
                    /* Refresh the shopping cart on the masterpage */
                    decimal[] cartContents = CartManagement.RefreshShoppingCart(c.Games);
                    Session["cartPrice"] = cartContents;

                    LinkButton lbCartInfo = ((LoginView)Page.Master.FindControl("LoginView1")).FindControl("lbCartInfo") as LinkButton;
                    lbCartInfo.Text = cartContents[1] + " artikel(en) totaalprijs: € " + String.Format("{0:0,##}",
                    cartContents[0].ToString().Replace('.', ','));
                }
            }
        }
    }

    /*
     * Function that checks whether the user is logged in or not.
     * 
     * If the user is logged in, the review window will be displayed.
     * If the user is not logged in, the login table will be shown.
     */
    private void ValidateUser()
    {
        if (Page.User.Identity.IsAuthenticated) { pnlLoggedIn.Visible = true; pnlNotLoggedIn.Visible = false; }
        else { pnlLoggedIn.Visible = false; pnlNotLoggedIn.Visible = true; }
    }

    /*
     * Function to check if the user that is logged in, has allready written a review of the Game.
     */
    private void CheckUserReview()
    {
        try
        {
            CustomMembershipProvider provider = Membership.Provider as CustomMembershipProvider;
            /* Check if the user has allready written a review of this Game */
            int userId = provider.GetUserId(Page.User.Identity.Name);
            string[] queryString = Request.QueryString["g"].Split('_');

            if ((DatabaseStore.CheckGameReview(userId, int.Parse(queryString[0])) == 1))
            {
                pnlLoggedInPositiveReview.Visible = true;
                pnlLoggedIn.Visible = false;
                pnlNotLoggedIn.Visible = false;
            }
            else
            {
                pnlLoggedInPositiveReview.Visible = false;
                pnlLoggedIn.Visible = true;
                pnlNotLoggedIn.Visible = false;
            }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception while checking user review status", "GAMEDETAILS");
            Log.CreateLog(ex.Message, "GAMEDETAILS");

            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de reviews. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
            pnlContents.Visible = false;
        }
    }

    /*
     * Function to get the five last written reviews for the selected Game.
     */ 
    private void GetGameReviews()
    {
        try
        {
            _reviews = new List<Review>();
            string[] queryString = Request.QueryString["g"].Split('_');
            if (!ReviewManagement.GetReviews(int.Parse(queryString[0]), _reviews))
            {
                /* Set the error message using the ErrorTable UserControl */
                ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de reviews. Probeer het nogmaals.";
                ucErrors._pnlVisibility = true;
                pnlContents.Visible = false;
            }
            else
            {
                rpReviews.DataSource = _reviews;
                rpReviews.DataBind();
            }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception while setting Favorite Game details", "GAMEDETAILS");
            Log.CreateLog(ex.Message, "GAMEDETAILS");

            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij het ophalen van de reviews. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
            pnlContents.Visible = false;
        }
    }

    /*
     * Function that is executed when the Repeater rpReviews is loaded.
     * 
     * Format's the DateTime string for the lblReviewDate Label.
     * Concat's the Text string if the length is above 250 characters.
     */ 
    protected void rpReviews_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Label lblReviewDate = e.Item.FindControl("lblReviewDate") as Label;
            Label lblReviewText = e.Item.FindControl("lblReviewText") as Label;
            Label lblReviewUser = e.Item.FindControl("lblReviewUser") as Label;
            HiddenField hfUserId = e.Item.FindControl("hfUserId") as HiddenField;
            LinkButton lbReadMore = e.Item.FindControl("lbReadMore") as LinkButton;
            Label lblBlock1 = e.Item.FindControl("lblBlock1") as Label;
            Label lblBlock2 = e.Item.FindControl("lblBlock2") as Label;

            if (lblReviewDate != null)
            {
                DateTime tempDate = DateTime.Parse(lblReviewDate.Text);
                lblReviewDate.Text = tempDate.ToString("dd-MM-yyyy");
            }
            if (lblReviewText != null)
            {
                if (lblReviewText.Text.Length > 250) { 
                    lblReviewText.Text = lblReviewText.Text.Substring(0, 250);
                    lblReviewText.Text += "....";
                    if (lbReadMore != null) { lbReadMore.Visible = true; lblBlock1.Visible = true; lblBlock2.Visible = true; }
                }
            }
            if (hfUserId != null)
            {
                CustomMembershipProvider provider = Membership.Provider as CustomMembershipProvider;
                User user = provider.GetUser(int.Parse(hfUserId.Value));
                if (user != null && lblReviewUser != null) { lblReviewUser.Text = user.FirstName + " " + user.LastName; }
            }
        }
    }

    /*
     * Function that is executed when the LinkButton lbViewFavorites is clicked.
     * 
     * Display's the View with the favorite games.
     */
    protected void SeeViewFavorites(object sender, EventArgs e)
    {
        lblTitle.Text = lblGameTitle.Text;
        lblPlatform.Text = lblGamePlatform.Text;
        MultiView1.ActiveViewIndex = 1;
        _viewIndex = MultiView1.ActiveViewIndex;

        /* Set LinkButton's to enabled or disabled */
        lbViewFavorites.Enabled = false;
        lbViewGameDetails.Enabled = true;
        lbViewReviews.Enabled = true;
    }

    /*
     * Function that is executed when the LinkButton lbViewReviews is clicked.
     * 
     * Display's the View with the game reviews.
     */
    protected void SeeViewReviews(object sender, EventArgs e)
    {
        ValidateUser();
        MultiView1.ActiveViewIndex = 2;
        _viewIndex = MultiView1.ActiveViewIndex;

        /* Set LinkButton's to enabled or disabled */
        lbViewReviews.Enabled = false;
        lbViewGameDetails.Enabled = true;
        lbViewFavorites.Enabled = true;

        /* Get the five last added reviews for the selected Game */
        GetGameReviews();

        /* Check if the user is authenticated and check if the user has allready written a review for this Game */
        if (Page.User.Identity.IsAuthenticated) { CheckUserReview(); }

        /* Get the average amount of points that where given to the selected game */
        decimal totalPoints = 0;
        foreach (RepeaterItem rpi in rpReviews.Items)
        {
            totalPoints += decimal.Parse(((Label)rpi.FindControl("lblReviewCipher")).Text);
        }

        decimal avgPoints = totalPoints / rpReviews.Items.Count;
        lblAveragePoints.Text = avgPoints.ToString("N1");
        lblAmountOfReviews.Text = rpReviews.Items.Count.ToString();
    }

    /*
     * Function that is executed when the LinkButton lbViewGameDetails is clicked.
     * 
     * Display's the View with the game details.
     */
    protected void SeeViewGameDetails(object sender, EventArgs e)
    {
        MultiView1.ActiveViewIndex = 0;
        _viewIndex = MultiView1.ActiveViewIndex;

        /* Set LinkButton's to enabled or disabled */
        lbViewGameDetails.Enabled = false;
        lbViewReviews.Enabled = true;
        lbViewFavorites.Enabled = true;
    }

    /*
     * Function that add's a new Game review into the database.
     */
    protected void AddGameReview(object sender, EventArgs e)
    {
        try
        {
            CustomMembershipProvider provider = Membership.Provider as CustomMembershipProvider;
            string[] queryString = Request.QueryString["g"].Split('_');

            Review rv = new Review
            {
                GameNr = int.Parse(queryString[0]),
                UserId = provider.GetUserId(Page.User.Identity.Name),
                Text = txtWriteReview.Text,
                Cipher = decimal.Parse(txtReviewPoints.Text),
                Date = DateTime.Now
            };

            if (!ReviewManagement.AddReview(rv))
            {
                /* Set the error message using the ErrorTable UserControl */
                ucErrors._labelText = "Er is een fout opgetreden bij toevoegen van de review. Probeer het nogmaals.";
                ucErrors._pnlVisibility = true;
                pnlContents.Visible = false;
            }
            else
            {
                Thread.Sleep(50);
                _reviews = new List<Review>();
                ReviewManagement.GetReviews(int.Parse(queryString[0]), _reviews);
                rpReviews.DataSource = _reviews;
                rpReviews.DataBind();

                /* Get the average amount of points that where given to the selected game */
                decimal totalPoints = 0;
                foreach (RepeaterItem rpi in rpReviews.Items)
                {
                    totalPoints += decimal.Parse(((Label)rpi.FindControl("lblReviewCipher")).Text);
                }

                decimal avgPoints = totalPoints / rpReviews.Items.Count;
                lblAveragePoints.Text = avgPoints.ToString("N1");
                lblAmountOfReviews.Text = rpReviews.Items.Count.ToString();

                pnlLoggedInPositiveReview.Visible = true;
                pnlLoggedIn.Visible = false;
                pnlNotLoggedIn.Visible = false;
            }
        }
        catch (Exception ex)
        {
            Log.CreateLog("Exception while inserting Game Review", "GAMEDETAILS");
            Log.CreateLog(ex.Message, "GAMEDETAILS");

            /* Set the error message using the ErrorTable UserControl */
            ucErrors._labelText = "Er is een fout opgetreden bij toevoegen van de review. Probeer het nogmaals.";
            ucErrors._pnlVisibility = true;
            pnlContents.Visible = false;
        }
    }

    /*
     * Function that is executed when the LinkButton lbReadMore is clicked.
     * 
     * Open's a a window with the rest of the Review.
     */ 
    protected void ReadMore(object sender, EventArgs e)
    {

    }

    /*
     * Function that is executed when the LinkButton lbBackToSearchResults is clicked.
     * 
     * Sends the user back to the page with search results.
     */
    protected void BackToSearchResults(object sender, EventArgs e)
    {
        Response.Redirect("~/Search.aspx?q=" + ((LinkButton)sender).CommandArgument);
    }
}
